package com.boruan.shengtangfeng.api.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.boruan.shengtangfeng.core.dao.*;
import com.boruan.shengtangfeng.core.entity.*;
import com.boruan.shengtangfeng.core.tencentEntity.CreateGroupReturn;
import com.boruan.shengtangfeng.core.utils.*;
import com.tencentyun.TLSSigAPIv2;
import org.apache.commons.lang3.RegExUtils;
import org.beetl.sql.core.db.KeyHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.boruan.shengtangfeng.api.jwt.util.JwtUtil;
import com.boruan.shengtangfeng.api.service.ILoginService;
import com.boruan.shengtangfeng.core.dto.BindMobileDto;
import com.boruan.shengtangfeng.core.dto.GetMobileCodeDto;
import com.boruan.shengtangfeng.core.dto.PasswordLoginDto;
import com.boruan.shengtangfeng.core.dto.RegisterDto;
import com.boruan.shengtangfeng.core.dto.SmsLoginDto;
import com.boruan.shengtangfeng.core.dto.UpdatePassDto;
import com.boruan.shengtangfeng.core.dto.WxLoginDto;
import com.boruan.shengtangfeng.core.enums.Sex;
import com.boruan.shengtangfeng.core.service.IUserService;
import com.boruan.shengtangfeng.core.utils.weixin.WeChatAuthService;
import com.boruan.shengtangfeng.core.vo.LoginResult;
import com.boruan.shengtangfeng.core.vo.NoticeVo;
import com.boruan.shengtangfeng.core.vo.UserVo;
import com.boruan.shengtangfeng.core.vo.mapper.UserVoMapper;

import cn.jpush.api.JPushClient;
import lombok.extern.slf4j.Slf4j;

/**
 * @author: 刘光强
 * @Description:
 * @date:2020年3月10日 上午11:14:10
 */
@SuppressWarnings("all")
@Service
@Slf4j
@Transactional(readOnly = true)
public class LoginService implements ILoginService {
    @Autowired
    private IUserDao userDao;
    @Autowired
    private IConfigDao configDao;
    @Value("${aliyun.sms.product}")
    private String product;
    @Value("${aliyun.sms.domain}")
    private String domain;
    @Value("${aliyun.sms.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.sms.accessKeySecret}")
    private String accessKeySecret;
    @Value("${aliyun.sms.templateCode.register}")
    private String templateCodeRegister;
    @Value("${aliyun.sms.templateCode.login}")
    private String templateCodeLogin;
    @Value("${aliyun.sms.templateCode.changePassword}")
    private String templateCodeChangePassword;
    @Value("${aliyun.sms.templateCode.changeMobile}")
    private String templateCodeChangeMobile;
    @Value("${aliyun.sms.signName}")
    private String signName;
    @Value("${jwt.expiration}")
    private Long expiration; // 过期时间
    @Autowired
    private JwtUtil jwtUtil;
    @Value("${jwt.tokenHead}")
    private String tokenHead;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private WeChatAuthService weChatAuthService;
    @Autowired
    private IUserService userService;
    @Autowired
    private JPushClient jPushClient;
    @Autowired
    private IArticleCategoryDao articleCategoryDao;
    @Autowired
    private IVideoCategoryDao videoCategoryDao;
    @Autowired
    private IUserCategoryDao userCategoryDao;
    @Autowired
    private IClassAndDao classAndDao;
    @Autowired
    private IClassMembersDao classMembersDao;
    @Autowired
    private IGroupChatDao groupChatDao;
    @Autowired
    private IGroupMembersDao groupMembersDao;
    @Autowired
    private IUserFriendAndBlacklistDao userFriendAndBlacklistDao;
    @Autowired
    private TencentUtil tencentUtil;
    @Value("${tencent.secretid}")
    private Long SECRETID;
    @Value("${tencent.secretkey}")
    private String SECRETKEY;
    @Autowired
    private ISubjectDao subjectDao;
    @Autowired
    private IUserCreateFansDao userCreateFansDao;

    //默认过期时间 365天
    private long expire=(long) 60 * 60 * 24 * 365;


    @Override
    @Transactional(readOnly = false)
    public GlobalReponse<LoginResult> passwordLogin(PasswordLoginDto passwordLoginDto) {
        User user = userDao.findByLoginName(passwordLoginDto.getLoginName());
        if (user == null) {
            return GlobalReponse.fail("用户不存在");
        }
        if (user.getIsLocked() == true) {
            return GlobalReponse.fail("用户已被锁定，请联系客服");
        }
        if (user.getIsDeleted() == true) {
            return GlobalReponse.fail("用户已注销，请联系客服");
        }
        if (StringUtils.isBlank(user.getPassword()) || StringUtils.isBlank(user.getSalt())) {
            return GlobalReponse.fail("密码未设置，不能使用密码登录");
        }
        boolean match = UserUtil.match(passwordLoginDto.getPassword(), user.getPassword(), user.getSalt());
        LoginResult result = new LoginResult();
        if (match) {
            //新增登录时间
            user.setLoginTime(new Date());
            user.setUpdateTime(new Date());
            TLSSigAPIv2 api = new TLSSigAPIv2(SECRETID, SECRETKEY);
            String userSig = api.genSig(user.getId().toString(), expire);
            user.setUserSig(userSig);
            userDao.updateById(user);

            result.setStatus(1);
            UserVo userVo = UserVoMapper.MAPPER.toVo(user);
            userVo.setUserSig(userSig);
            result.setUser(userVo);
            String token = jwtUtil.generateToken(user.getId(), user.getMobile(), user.getName(), null,
                    user.getHeadImage());
            result.setToken(tokenHead + token);
            if (StringUtils.isBlank(user.getPassword())) {
                userVo.setHavePassword(false);
            } else {
                userVo.setHavePassword(true);
            }
            redisTemplate.opsForValue().set(Consts.USER_TOKEN_KEY + user.getId(), token);
            //推自定义消息让前端清空token
            NoticeVo noticeVo = new NoticeVo();
            noticeVo.setUserId(user.getId());
            noticeVo.setType(404);
            noticeVo.setTitle("账号互踢,强制下线");

            JPushMessage pushMessage = new JPushMessage();
            pushMessage.setMsgContent("账号互踢,强制下线");
            pushMessage.setExtras(new HashMap<String, String>() {{
                put("code", "404");
                put("time", passwordLoginDto.getTime());
            }});
            PushUtil.push(jPushClient, noticeVo, pushMessage);
            return GlobalReponse.success(result);
        }
        return GlobalReponse.fail("密码错误");
    }

    @Override
    @Transactional(readOnly = false)
    public GlobalReponse<LoginResult> wxLogin(WxLoginDto wxLoginDto) {
        Map<String, String> weixinResult = weChatAuthService.getAccessToken(wxLoginDto.getCode());
        String openId = weixinResult.get("openid");
        String accessToken = weixinResult.get("accessToken");
        redisTemplate.opsForValue().set(Consts.REDIS_ACCECC_TOKEN_KEY + openId, accessToken, 60, TimeUnit.MINUTES);
        User user = userDao.findByOpenId(openId);
        LoginResult result = new LoginResult();
        if (user == null) {
            // 用户为空，则让用户去绑定用户
            result.setStatus(2);
            result.setOpenId(openId);
        } else {
            if (user.getIsLocked() == true) {
                return GlobalReponse.fail("用户已被锁定，请联系客服");
            }
            if (user.getIsDeleted() == true) {
                return GlobalReponse.fail("用户已注销，请联系客服");
            }
            result.setStatus(1);
            //新增登录时间
            user.setLoginTime(new Date());
            user.setUpdateTime(new Date());
            TLSSigAPIv2 api = new TLSSigAPIv2(SECRETID, SECRETKEY);
            String userSig = api.genSig(user.getId().toString(), expire);
            user.setUserSig(userSig);
            userDao.updateById(user);

            UserVo userVo = UserVoMapper.MAPPER.toVo(user);
            userVo.setUserSig(userSig);
            if (StringUtils.isBlank(user.getPassword())) {
                userVo.setHavePassword(false);
            } else {
                userVo.setHavePassword(true);
            }
            result.setUser(userVo);
            String token = jwtUtil.generateToken(user.getId(), user.getMobile(), user.getName(), user.getOpenId(),
                    user.getHeadImage());
            result.setToken(tokenHead + token);

            redisTemplate.opsForValue().set(Consts.USER_TOKEN_KEY + user.getId(), token);
            //推自定义消息让前端清空token
            NoticeVo noticeVo = new NoticeVo();
            noticeVo.setUserId(user.getId());
            noticeVo.setType(404);
            noticeVo.setTitle("账号互踢,强制下线");

            JPushMessage pushMessage = new JPushMessage();
            pushMessage.setMsgContent("账号互踢,强制下线");
            pushMessage.setExtras(new HashMap<String, String>() {{
                put("code", "404");
                put("time", wxLoginDto.getTime());
            }});
            PushUtil.push(jPushClient, noticeVo, pushMessage);
        }
        return GlobalReponse.success(result);
    }

    @Override
    @Transactional(readOnly = false)
    public GlobalReponse<LoginResult> smsLogin(SmsLoginDto smsLoginDto) {
        String codeRedis = (String) redisTemplate.opsForValue().get(Consts.sendCode + smsLoginDto.getMobile());
        if (!StringUtils.equals(smsLoginDto.getAuthCode(), codeRedis)) {
            return GlobalReponse.fail("验证码错误");
        } else {
            redisTemplate.delete(Consts.sendCode + smsLoginDto.getMobile()); // 验证成功删除redis存在的验证码
        }
        User user = userDao.findByMobile(smsLoginDto.getMobile());
        if (user == null) {
            // 用户不存在需要自动注册
            user = buildNewUser(smsLoginDto.getMobile(), null, null, 1);
            TLSSigAPIv2 api = new TLSSigAPIv2(SECRETID, SECRETKEY);
            String userSig = api.genSig(user.getId().toString(), expire);
            user.setUserSig(userSig);
            userDao.updateTemplateById(user);
            UserVo userVo = UserVoMapper.MAPPER.toVo(user);
            userVo.setUserSig(userSig);
            // this.userInfo(user, userVo);
            LoginResult loginResult = new LoginResult();
            loginResult.setStatus(1);
            loginResult.setUser(userVo);
            String token = jwtUtil.generateToken(user.getId(), user.getMobile(), user.getName(), user.getOpenId(),
                    user.getHeadImage());
            loginResult.setToken(tokenHead + token);

            redisTemplate.opsForValue().set(Consts.USER_TOKEN_KEY + user.getId(), token);
            //推自定义消息让前端清空token
            NoticeVo noticeVo = new NoticeVo();
            noticeVo.setUserId(user.getId());
            noticeVo.setType(404);
            noticeVo.setTitle("账号互踢,强制下线");

            JPushMessage pushMessage = new JPushMessage();
            pushMessage.setMsgContent("账号互踢,强制下线");
            pushMessage.setExtras(new HashMap<String, String>() {{
                put("code", "404");
                put("time", smsLoginDto.getTime());
            }});
            PushUtil.push(jPushClient, noticeVo, pushMessage);
            return GlobalReponse.success(loginResult);
        }
        if (user.getIsLocked() == true) {
            return GlobalReponse.fail("用户已被锁定，请联系客服");
        }
        if (user.getIsDeleted() == true) {
            return GlobalReponse.fail("用户已注销，请联系客服");
        }
        LoginResult result = new LoginResult();

        //新增登录时间
        user.setLoginTime(new Date());
        user.setUpdateTime(new Date());

        userDao.updateById(user);
        result.setStatus(1);
        UserVo userVo = UserVoMapper.MAPPER.toVo(user);
        if (StringUtils.isBlank(user.getPassword())) {
            userVo.setHavePassword(false);
        } else {
            userVo.setHavePassword(true);
        }
        result.setUser(userVo);
        String token = jwtUtil.generateToken(user.getId(), user.getMobile(), user.getName(), user.getOpenId(),
                user.getHeadImage());
        result.setToken(tokenHead + token);
        return GlobalReponse.success(result);
    }

    /**
     * @param :type:1用户注册验证码, 2登录确认验证码, 3修改密码验证码
     * @author: 刘光强
     * @Description: 获取验证码
     * @date:2020年3月10日 上午11:14:10
     */
    @Override
    public GlobalReponse<String> getVerficationCode(GetMobileCodeDto getMobileCodeDto) {
        try {
            // 初始化acsClient,暂不支持region化
            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
            IAcsClient acsClient = new DefaultAcsClient(profile);
            SendSmsRequest request = new SendSmsRequest();
            request.setPhoneNumbers(getMobileCodeDto.getMobile());
            request.setSignName(signName);
            switch (getMobileCodeDto.getType()) {
                case 1:
                    request.setTemplateCode(templateCodeRegister);
                    break;
                case 2:
                    request.setTemplateCode(templateCodeLogin);
                    break;
                case 3:
                    request.setTemplateCode(templateCodeChangePassword);
                    break;
                case 4:
                    request.setTemplateCode(templateCodeChangeMobile);
                    User user = userService.findByMobile(getMobileCodeDto.getMobile());
                    if (user != null && StringUtils.isNotBlank(user.getOpenId())) {
                        return GlobalReponse.fail("该手机已经绑定过微信");
                    }
                    break;
            }
            String code = StringUtils.createCharacterNumber();
//            code = "000000";
            request.setTemplateParam("{code:" + code + "}");
            redisTemplate.opsForValue().set(Consts.sendCode + getMobileCodeDto.getMobile(), code, 5, TimeUnit.MINUTES);
//            return GlobalReponse.success("验证码发送成功", code);
            SendSmsResponse response = acsClient.getAcsResponse(request);
            if ("OK".equals(response.getCode())) {
                redisTemplate.opsForValue().set(Consts.sendCode + getMobileCodeDto.getMobile(), code, 5, TimeUnit.MINUTES);
                return GlobalReponse.success("验证码发送成功", code);
            } else {
                return GlobalReponse.fail(response.getMessage());
            }

        } catch (Exception e) {
            e.printStackTrace();
            return GlobalReponse.fail("发送验证码失败！");
        }
    }

    /**
     * @author: 刘光强
     * @Description: 处理绑定手机号
     * @date:2020年3月10日 上午11:14:10
     */
    @Override
    @Transactional(readOnly = false)
    public GlobalReponse<LoginResult> bindingMobile(BindMobileDto bindMobileDto) {

        String codeRedis = (String) redisTemplate.opsForValue().get(Consts.sendCode + bindMobileDto.getMobile());
        if (!StringUtils.equals(bindMobileDto.getAuthCode(), codeRedis)) {
            return GlobalReponse.fail("验证码错误");
        } else {
            redisTemplate.delete(Consts.sendCode + bindMobileDto.getMobile()); // 验证成功删除redis存在的验证码
        }
        User user = userDao.findByMobile(bindMobileDto.getMobile()); // 根据手机号查用户是否注册过
        if (user == null) {
            // 用户不存在需要自动注册
            user = buildNewUser(bindMobileDto.getMobile(), bindMobileDto.getOpenId(), null, bindMobileDto.getUserType());
            UserVo userVo = UserVoMapper.MAPPER.toVo(user);

            // this.userInfo(user, userVo);
            LoginResult loginResult = new LoginResult();
            loginResult.setStatus(1);
            loginResult.setUser(userVo);
            String token = jwtUtil.generateToken(user.getId(), user.getMobile(), user.getName(), user.getOpenId(),
                    user.getHeadImage());
            loginResult.setToken(tokenHead + token);
            redisTemplate.opsForValue().set(Consts.USER_TOKEN_KEY + user.getId(), token);
            //推自定义消息让前端清空token
            NoticeVo noticeVo = new NoticeVo();
            noticeVo.setUserId(user.getId());
            noticeVo.setType(404);
            noticeVo.setTitle("账号互踢,强制下线");

            JPushMessage pushMessage = new JPushMessage();
            pushMessage.setMsgContent("账号互踢,强制下线");
            pushMessage.setExtras(new HashMap<String, String>() {{
                put("code", "404");
                put("time", bindMobileDto.getTime());
            }});
            PushUtil.push(jPushClient, noticeVo, pushMessage);
            return GlobalReponse.success(loginResult);
        } else if (StringUtils.isNotBlank(user.getOpenId())) {
            return GlobalReponse.fail("该手机号已绑定其他账号");
        } else {
            if (user.getIsLocked() == true) {
                return GlobalReponse.fail("用户已被锁定，请联系客服");
            }
            if (user.getIsDeleted() == true) {
                return GlobalReponse.fail("用户已注销，请联系客服");
            }
            user.setOpenId(bindMobileDto.getOpenId());

            //从redis获取到授权token获取用户信息
            String accessToken = (String) redisTemplate.opsForValue().get(Consts.REDIS_ACCECC_TOKEN_KEY + bindMobileDto.getOpenId());
            if (StringUtils.isNotBlank(accessToken)) {
                try {
                    JSONObject json = weChatAuthService.getUserInfo(accessToken, bindMobileDto.getOpenId());
                    String nickname = json.getString("nickname");
                    String headimgurl = json.getString("headimgurl");
                    Integer sex = json.getInteger("sex");
                    String country = json.getString("country");
                    String province = json.getString("province");
                    String city = json.getString("city");
                    if (StringUtils.isBlank(user.getName())) {
                        user.setName(nickname);
                    }
                    if (StringUtils.isBlank(user.getHeadImage())) {
                        user.setHeadImage(headimgurl);
                    }
                    user.setSex(EnumUtil.getEnumByValue(Sex.class, sex));
                } catch (Exception e) {
                }

            }

            userDao.updateById(user);
            LoginResult loginResult = new LoginResult();
            loginResult.setStatus(1);
            UserVo userVo = UserVoMapper.MAPPER.toVo(user);
            if (StringUtils.isBlank(user.getPassword())) {
                userVo.setHavePassword(false);
            } else {
                userVo.setHavePassword(true);
            }
            loginResult.setUser(userVo);
            String token = jwtUtil.generateToken(user.getId(), user.getMobile(), user.getName(), user.getOpenId(),
                    user.getHeadImage());
            loginResult.setToken(tokenHead + token);
            redisTemplate.opsForValue().set(Consts.USER_TOKEN_KEY + user.getId(), token);
            //推自定义消息让前端清空token
            NoticeVo noticeVo = new NoticeVo();
            noticeVo.setUserId(user.getId());
            noticeVo.setType(404);
            noticeVo.setTitle("账号互踢,强制下线");

            JPushMessage pushMessage = new JPushMessage();
            pushMessage.setMsgContent("账号互踢,强制下线");
            pushMessage.setExtras(new HashMap<String, String>() {{
                put("code", "404");
                put("time", bindMobileDto.getTime());
            }});
            PushUtil.push(jPushClient, noticeVo, pushMessage);
            return GlobalReponse.success(loginResult);
        }
    }

    /**
     * @author: 刘光强
     * @Description: 验证手机号是否注册过
     * @date:2020年3月10日 上午11:14:10
     */
    @Override
    public GlobalReponse<Boolean> verificationMobile(String mobile) {
        if (StringUtils.isRealBlank(mobile)) {
            return GlobalReponse.fail("手机号不能为空！");
        }
        User user = userDao.findByMobile(mobile); // 根据手机号查用户是否注册过
        if (user != null) {
            return GlobalReponse.success(false);
        }
        return GlobalReponse.success(true);

    }

    /**
     * @author: 刘光强
     * @Description: 忘记密码或者修改密码
     * @date:2020年3月10日 上午11:14:10
     */
    @Override
    @Transactional(readOnly = false)
    public GlobalReponse updatePassword(UpdatePassDto updatePassDto) {
        String codeRedis = (String) redisTemplate.opsForValue().get(Consts.sendCode + updatePassDto.getMobile());
        if (!StringUtils.equals(updatePassDto.getAuthCode(), codeRedis)) {
            return GlobalReponse.fail("验证码错误");
        } else {
            redisTemplate.delete(Consts.sendCode + updatePassDto.getMobile()); // 验证成功删除redis存在的验证码
        }
        User user = userDao.findByMobile(updatePassDto.getMobile()); // 根据手机号查用户是否注册过
        if (user != null) {
            user.setSalt(UserUtil.getSalt());
            user.setPassword(UserUtil.entryptPassword(updatePassDto.getPassword(), user.getSalt()));
            userDao.updateById(user);
            return GlobalReponse.success();
        } else {
            return GlobalReponse.fail("用户不存在");
        }

    }

    /**
     * @author: 刘光强
     * @Description: 用户注册
     * @date:2020年3月10日 上午11:14:10
     */
    @Override
    @Transactional(readOnly = false)
    public GlobalReponse<LoginResult> register(RegisterDto registerDto) {
        try {
            String codeRedis = (String) redisTemplate.opsForValue().get(Consts.sendCode + registerDto.getMobile());
            if (!StringUtils.equals(registerDto.getAuthCode(), codeRedis)) {
                return GlobalReponse.fail("验证码错误");
            } else {
                redisTemplate.delete(Consts.sendCode + registerDto.getMobile()); // 验证成功删除redis存在的验证码
            }
            User user = userDao.findByMobile(registerDto.getMobile()); // 根据手机号查用户是否注册过
            if (user != null) {
                return GlobalReponse.fail("用户已经存在");
            } else {
                user = buildNewUser(registerDto.getMobile(), null, registerDto.getPassword(), registerDto.getUserType());
                Integer len = Math.toIntExact(8 - (user.getId() + "").length());
                user.setAccount(user.getId() + UUIDUtil.differentDigitsRandom(len));
                TLSSigAPIv2 api = new TLSSigAPIv2(SECRETID, SECRETKEY);
                String userSig = api.genSig(user.getId().toString(), expire);
                user.setUserSig(userSig);
                userDao.updateTemplateById(user);
                UserVo userVo = UserVoMapper.MAPPER.toVo(user);
                userVo.setUserSig(userSig);
                // this.userInfo(user, userVo);
                LoginResult loginResult = new LoginResult();
                loginResult.setStatus(1);
                loginResult.setUser(userVo);
                String token = jwtUtil.generateToken(user.getId(), user.getMobile(), user.getName(), user.getOpenId(),
                        user.getHeadImage());
                loginResult.setToken(tokenHead + token);
                //推自定义消息让前端清空token
                NoticeVo noticeVo = new NoticeVo();
                noticeVo.setUserId(user.getId());
                noticeVo.setType(404);
                noticeVo.setTitle("账号互踢,强制下线");

                JPushMessage pushMessage = new JPushMessage();
                pushMessage.setMsgContent("账号互踢,强制下线");
                pushMessage.setExtras(new HashMap<String, String>() {{
                    put("code", "404");
                    put("time", registerDto.getTime());
                }});
                PushUtil.push(jPushClient, noticeVo, pushMessage);
                return GlobalReponse.success(loginResult);
            }
        } catch (Exception e) {
            log.error("用户注册 异常：", e);
            return GlobalReponse.fail();
        }
    }

    private User buildNewUser(String mobile, String openId, String password, Integer userType) {
        User user = new User();
        user.setCreateTime(new Date());
        user.setIsDeleted(false);
        user.setIsLocked(false);
        user.setMobile(mobile);
        user.setType(0);
        user.setLoginName(mobile);
        user.setUserType(userType);
        if (StringUtils.isNotBlank(user.getMobile())) {
            user.setName(RegExUtils.replaceAll(user.getMobile(), "(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
        }
        Config config = configDao.getKey(Consts.CONFIG_USER_ICON);
        user.setHeadImage(config.getValue());
        user.setAccurate(new BigDecimal(0));
        user.setAnswerNum(0);
        user.setChangeMobile(true);
        user.setLikeNum(0);
        user.setIntegral(0);
        user.setSex(Sex.UNKNOW);
        user.setShowLocation(0);
        if (StringUtils.isNotBlank(password)) {
            user.setSalt(UserUtil.getSalt());
            user.setPassword(UserUtil.entryptPassword(password, user.getSalt()));
        } else {
//          user.setPassword(UserUtil.entryptPassword(UUIDUtil.getUUID(), user.getSalt()));
        }
        if (!StringUtils.isRealBlank(openId)) {
            user.setOpenId(openId);
            String accessToken = (String) redisTemplate.opsForValue().get(Consts.REDIS_ACCECC_TOKEN_KEY + openId);
            if (StringUtils.isNotBlank(accessToken)) {
                try {
                    JSONObject json = weChatAuthService.getUserInfo(accessToken, openId);
                    String nickname = json.getString("nickname");
                    String headimgurl = json.getString("headimgurl");
                    Integer sex = json.getInteger("sex");
                    String country = json.getString("country");
                    String province = json.getString("province");
                    String city = json.getString("city");
                    user.setName(nickname);
                    user.setHeadImage(headimgurl);
                    user.setSex(EnumUtil.getEnumByValue(Sex.class, sex));
                } catch (Exception e) {
                }

            }
        }
        KeyHolder keyHolder = userDao.insertReturnKey(user);
        user.setId(keyHolder.getLong());

        UserCategory userCategory = new UserCategory();
        //创建新用户先增加文章默认类别
        List<ArticleCategory> articleCategoryList = articleCategoryDao.getArticleCategoryDefault();
        List<VideoCategory> videoCategoriesList = videoCategoryDao.getVideoCategoryDefault();
        List<Subject> subjectList = subjectDao.createLambdaQuery().andEq(Subject::getIsDeleted, false).andEq(Subject::getIsDefault, 1).select();

        userCategory.setCreateTime(new Date());
        userCategory.setIsDeleted(false);
        for (int i = 0; i < articleCategoryList.size(); i++) {//默认文章
            userCategory.setUserId(keyHolder.getLong());
            userCategory.setCategoryId(articleCategoryList.get(i).getId());
            userCategory.setCategoryType(1);
            userCategoryDao.insertReturnKey(userCategory);
        }
        for (int i = 0; i < videoCategoriesList.size(); i++) {//默认视频
            userCategory.setCreateTime(new Date());
            userCategory.setUserId(keyHolder.getLong());
            userCategory.setCategoryId(videoCategoriesList.get(i).getId());
            userCategory.setCategoryType(videoCategoriesList.get(i).getType());
            userCategoryDao.insertReturnKey(userCategory);
        }
        for (Subject subject : subjectList) {
            userCategory.setCreateTime(new Date());
            userCategory.setUserId(keyHolder.getLong());
            userCategory.setCategoryId(subject.getId());
            userCategory.setCategoryType(3);
            userCategoryDao.insertReturnKey(userCategory);
        }

        Config fansNum = configDao.getKey(Consts.CONFIG_FANS_NUM);
        Config fansday = configDao.getKey(Consts.CONFIG_FANS_DAY);
        double floor = Math.floor(Double.valueOf(fansNum.getValue()) / Double.valueOf(fansday.getValue()));
        long longValue = new Double(floor).longValue();

        ArrayList<UserCreateFans> fansArrayList = new ArrayList<>();
        Integer sum=0;
        for (Integer i = 0; i < Integer.valueOf(fansday.getValue()); i++) {
            UserCreateFans userCreateFans = new UserCreateFans();
            int num = new Random().nextInt(Integer.valueOf(String.valueOf(longValue)));
            userCreateFans.setUserId(user.getId());
            if (i==Integer.valueOf(fansday.getValue())-1){
                userCreateFans.setFansNum(Integer.valueOf(fansNum.getValue())-sum);
            }else {
                userCreateFans.setFansNum(num+1);
            }
            userCreateFans.setIsDeleted(false);
            userCreateFans.setIsExecute(0);
            userCreateFans.setCreateTime(new Date());
            userCreateFans.setCreateBy(user.getId().toString());
            fansArrayList.add(userCreateFans);
            sum+=num;
        }
        userCreateFansDao.insertBatch(fansArrayList);

        return user;
    }

    @Override
    @Transactional
    public GlobalReponse registerH5(String mobile, String authCode, Long spreadId) {
        try {
            if (StringUtils.isAnyEmpty(mobile, authCode)) {
                return GlobalReponse.fail("参数缺失：" + mobile + "-" + "-" + authCode);
            }
            String codeRedis = (String) redisTemplate.opsForValue().get(Consts.sendCode + mobile);
            if (!StringUtils.equals(authCode, codeRedis)) {
                return GlobalReponse.fail("验证码错误");
            } else {
                redisTemplate.delete(Consts.sendCode + mobile); // 验证成功删除redis存在的验证码
            }
            User user = userDao.findByMobile(mobile); // 根据手机号查用户是否注册过
            if (user != null) {
                return GlobalReponse.fail("用户已经存在");
            } else {
                user = buildNewUser(mobile, null, null, 1);
                TLSSigAPIv2 api = new TLSSigAPIv2(SECRETID, SECRETKEY);
                String userSig = api.genSig(user.getId().toString(), expire);
                user.setUserSig(userSig);
                userDao.updateTemplateById(user);
                UserVo userVo = UserVoMapper.MAPPER.toVo(user);
                userVo.setUserSig(userSig);
                return GlobalReponse.success(userVo);
            }
        } catch (Exception e) {
            log.error("用户注册 异常：", e);
            return GlobalReponse.fail();
        }
    }

    /**
     * 用户登出
     *
     * @param userId
     * @return
     */
    @Override
    public GlobalReponse logout(Long userId) {
        User user = userDao.unique(userId);
        user.setLogoutTime(new Date());
        user.setUpdateTime(new Date());
        userDao.updateById(user);
        return GlobalReponse.success("退出成功");
    }

    /**
     * 判断用户是否注册，注册了则加入班级
     *
     * @param mobile
     * @param classId
     * @return
     */
    @Override
    public GlobalReponse userIsRegistered(String mobile, Long classId) {
        User user = userDao.findByMobile(mobile); // 根据手机号查用户是否注册过
        if (user == null) {
            return GlobalReponse.fail("用户不存在");
        }
        ClassAnd classAnd = classAndDao.unique(classId);
        GroupChat groupChat = groupChatDao.createLambdaQuery().andEq(GroupChat::getClassId, classId).andEq(GroupChat::getIsDeleted, false).single();
        List<CreateGroupReturn> returns = tencentUtil.addGroupMember(groupChat.getId(), user.getId().toString(), 0);
        for (CreateGroupReturn aReturn : returns) {
            if (aReturn.getResult().equals("1")) {
                ClassMembers classMembers = new ClassMembers();
                classMembers.setClassId(classId);
                classMembers.setUserId(Long.valueOf(user.toString()));
                classMembers.setIsDeleted(false);
                classMembers.setCreateBy(user.getId().toString());
                classMembers.setNickname(user.getName());
                classMembers.setType(user.getUserType());
                classMembers.setHeadImage(user.getHeadImage());
                classMembersDao.insertTemplate(classMembers);
                GroupMembers groupMembers = new GroupMembers();
                groupMembers.setUserId(user.getId());
                groupMembers.setNickName(user.getName());
                groupMembers.setGroupChatId(groupChat.getId());
                groupMembers.setCreateBy(user.getId().toString());
                groupMembers.setCreateTime(new Date());
                if (user.getUserType() == 1) {
                    groupMembers.setType(0);
                } else if (user.getUserType() == 2) {
                    groupMembers.setType(1);
                }
                groupMembersDao.insertTemplate(groupMembers);
                UserFriendAndBlacklist friendAndBlacklist = new UserFriendAndBlacklist();
                friendAndBlacklist.setUserId(user.getId());
                friendAndBlacklist.setRelevanceId(groupChat.getId());
                friendAndBlacklist.setType(1);
                friendAndBlacklist.setIsDeleted(false);
                friendAndBlacklist.setCreateBy(user.getId().toString());
                friendAndBlacklist.setCreateTime(new Date());
                userFriendAndBlacklistDao.insertTemplate(friendAndBlacklist);
            }
        }
        return GlobalReponse.success("加入成功");
    }
}
